/*
Sader engine framework
(c) Rachel J. Morris
MIT License
www.moosader.com
*/

#include "Geometry.h"

namespace sader
{

Geometry::Geometry()
{
    Init();
}

void Geometry::Init()
{
    m_coord.x = m_coord.y = m_coord.z = 0;
    m_coord.w = m_coord.d = 32;
    m_coord.h = 16;
    m_film.w = m_film.h = 32;
    m_film.x = m_film.y = 0;
    m_film.z = m_film.d = 0;
    m_collision.x = m_collision.y = m_collision.z =
        m_collision.w = m_collision.h = m_collision.d;
}

void Geometry::SetCoordinates( float x, float y, float z )
{
    m_coord.x = x;
    m_coord.y = y;
    m_coord.z = z;
}

void Geometry::SetDimensions( float w, float h, float d )
{
    m_coord.w = w;
    m_coord.h = h;
    m_coord.d = d;
}

void Geometry::SetTexture( Texture& texture )
{
    this->m_texture = &texture;
}

void Geometry::Draw( DrawPlane drawPlane/*=CUBE*/ )
{
    if ( drawPlane == CUBE )
    {
        DrawCube();
    }
    else if ( drawPlane == XY )
    {
        DrawXY();
    }
    else if ( drawPlane == YZ )
    {
        DrawYZ();
    }
    else if ( drawPlane == XYYZ )
    {
        DrawXYYZ();
    }
}

void Geometry::DrawXY()
{
    // Temp
    float fw = m_texture->m_texture_w;
    float fh = m_texture->m_texture_h;

    glBindTexture( GL_TEXTURE_2D, m_texture->m_texture );
    glEnable( GL_TEXTURE_2D );

    glBegin( GL_QUADS );

        glColor3f( 1.0f, 1.0f, 1.0f );
        // Bottom Left
        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X1(), Y1(), Z1() );

        // Bottom Right
        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X2(), Y1(), Z1() );

        // Top Right
        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X2(), Y2(), Z1() );

        // Top Left
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X1(), Y2(), Z1() );

    glEnd();

    glDisable( GL_TEXTURE_2D );
}

void Geometry::DrawYZ()
{
    // Temp
    float fw = m_texture->m_texture_w;
    float fh = m_texture->m_texture_h;

    glBindTexture( GL_TEXTURE_2D, m_texture->m_texture );
    glEnable( GL_TEXTURE_2D );

    glBegin( GL_QUADS );

        glColor3f( 1.0f, 1.0f, 1.0f );
        // Bottom Left
        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X1(), Y1(), Z1() );

        // Bottom Right
        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X1(), Y1(), Z2() );

        // Top Right
        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X1(), Y2(), Z2() );

        // Top Left
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X1(), Y2(), Z1() );

    glEnd();

    glDisable( GL_TEXTURE_2D );
}

void Geometry::DrawXYYZ()
{
    // Temp
    float fw = m_texture->m_texture_w;
    float fh = m_texture->m_texture_h;

    glBindTexture( GL_TEXTURE_2D, m_texture->m_texture );
    glEnable( GL_TEXTURE_2D );

    glBegin( GL_QUADS );

        glColor3f( 1.0f, 1.0f, 1.0f );

        //XY
        // Bottom Left
        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X1(), Y1(), Z1() + D()/2 );

        // Bottom Right
        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X2(), Y1(), Z1() + D()/2 );

        // Top Right
        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X2(), Y2(), Z1() + D()/2 );

        // Top Left
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X1(), Y2(), Z1() + D()/2 );

        // YZ
        // Bottom Left
        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X1() + W()/2, Y1(), Z1() );

        // Bottom Right
        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X1() + W()/2, Y1(), Z2() );

        // Top Right
        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X1() + W()/2, Y2(), Z2() );

        // Top Left
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X1() + W()/2, Y2(), Z1() );

    glEnd();

    glDisable( GL_TEXTURE_2D );
}

void Geometry::DrawCube()
{
    // Temp
    float fw = m_texture->m_texture_w;
    float fh = m_texture->m_texture_h;

    glBindTexture( GL_TEXTURE_2D, m_texture->m_texture );
    glEnable( GL_TEXTURE_2D );

    glBegin( GL_QUADS );

        /* XZ top ******************************/
        glColor3f( 1.0f, 1.0f, 1.0f );
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X1(), Y2(), Z1() );

        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X2(), Y2(), Z1() );

        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X2(), Y2(), Z2() );

        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X1(), Y2(), Z2() );

        /* XZ bottom ******************************/
        glColor3f( 0.6f, 0.6f, 0.6f );
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X1(), Y1(), Z1() );

        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X2(), Y1(), Z1() );

        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X2(), Y1(), Z2() );

        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X1(), Y1(), Z2() );

        /* XY back ******************************/
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X1(), Y1(), Z1() );

        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X2(), Y1(), Z1() );

        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X2(), Y2(), Z1() );

        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X1(), Y2(), Z1() );

        /* XY front ******************************/
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X1(), Y1(), Z2() );

        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X2(), Y1(), Z2() );

        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X2(), Y2(), Z2() );

        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X1(), Y2(), Z2() );

        /* YZ left ******************************/
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X1(), Y1(), Z1() );

        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X1(), Y1(), Z2() );

        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X1(), Y2(), Z2() );

        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X1(), Y2(), Z1() );

        /* YZ right ******************************/
        glTexCoord2f( FX1( fw ), FY1( fh ) );
        glVertex3f( X2(), Y1(), Z1() );

        glTexCoord2f( FX2( fw ), FY1( fh ) );
        glVertex3f( X2(), Y1(), Z2() );

        glTexCoord2f( FX2( fw ), FY2( fh ) );
        glVertex3f( X2(), Y2(), Z2() );

        glTexCoord2f( FX1( fw ), FY2( fh ) );
        glVertex3f( X2(), Y2(), Z1() );
    glEnd();

    glDisable( GL_TEXTURE_2D );
}

void Geometry::DrawBoundingBox( float r, float g, float b )
{
    glBegin( GL_LINES );

        glColor3f( r, g, b );

        // Side 1
        glVertex3f( ColX1(), ColY1(), ColZ1() );
        glVertex3f( ColX1(), ColY2(), ColZ1() );

        glVertex3f( ColX2(), ColY2(), ColZ1() );
        glVertex3f( ColX2(), ColY1(), ColZ1() );

        glVertex3f( ColX1(), ColY1(), ColZ1() );
        glVertex3f( ColX2(), ColY1(), ColZ1() );

        glVertex3f( ColX1(), ColY2(), ColZ1() );
        glVertex3f( ColX2(), ColY2(), ColZ1() );

        // Side 2
        glVertex3f( ColX1(), ColY1(), ColZ1() );
        glVertex3f( ColX1(), ColY2(), ColZ1() );

        glVertex3f( ColX1(), ColY2(), ColZ2() );
        glVertex3f( ColX1(), ColY1(), ColZ2() );

        glVertex3f( ColX1(), ColY1(), ColZ1() );
        glVertex3f( ColX1(), ColY1(), ColZ2() );

        glVertex3f( ColX1(), ColY2(), ColZ1() );
        glVertex3f( ColX1(), ColY2(), ColZ2() );

        // Side 3
        glVertex3f( ColX1(), ColY1(), ColZ2() );
        glVertex3f( ColX1(), ColY2(), ColZ2() );

        glVertex3f( ColX2(), ColY2(), ColZ2() );
        glVertex3f( ColX2(), ColY1(), ColZ2() );

        glVertex3f( ColX1(), ColY1(), ColZ2() );
        glVertex3f( ColX2(), ColY1(), ColZ2() );

        glVertex3f( ColX1(), ColY2(), ColZ2() );
        glVertex3f( ColX2(), ColY2(), ColZ2() );

        // Side 4
        glVertex3f( ColX2(), ColY1(), ColZ1() );
        glVertex3f( ColX2(), ColY2(), ColZ1() );

        glVertex3f( ColX2(), ColY2(), ColZ2() );
        glVertex3f( ColX2(), ColY1(), ColZ2() );

        glVertex3f( ColX2(), ColY1(), ColZ1() );
        glVertex3f( ColX2(), ColY1(), ColZ2() );

        glVertex3f( ColX2(), ColY2(), ColZ1() );
        glVertex3f( ColX2(), ColY2(), ColZ2() );

    glEnd();
}

float Geometry::ColX1()
{
    return m_coord.x + m_collision.x;
}

float Geometry::ColX2()
{
    return m_coord.x + m_collision.x + m_collision.w;
}

float Geometry::ColY1()
{
    return m_coord.y + m_collision.y;
}

float Geometry::ColY2()
{
    return m_coord.y + m_collision.y + m_collision.h;
}

float Geometry::ColZ1()
{
    return m_coord.z + m_collision.z;
}

float Geometry::ColZ2()
{
    return m_coord.z + m_collision.z + m_collision.d;
}

void Geometry::SetCollisionRegion( float x, float y, float z, float w, float h, float d )
{
    m_collision.x = x;
    m_collision.w = w;
    m_collision.y = y;
    m_collision.h = h;
    m_collision.z = z;
    m_collision.d = d;
}

void Geometry::DrawShadow()
{
    // Too lazy for circles
    float haxY = 17;
    glBegin( GL_QUADS );
        glColor3f( 0.0f, 0.0f, 0.0f );
        glVertex3f( ColX1(), haxY, ColZ1() );
        glVertex3f( ColX2(), haxY, ColZ1() );
        glVertex3f( ColX2(), haxY, ColZ2() );
        glVertex3f( ColX1(), haxY, ColZ2() );
    glEnd();
}


}
